import {
  app,
  shell,
  BrowserWindow,
  ipcMain,
  dialog,
  globalShortcut,
  Menu,
  MenuItem,
  webContents
} from 'electron'
import { join } from 'path'
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/icon.png?asset'
const fs = require('fs')
const os = require('os')

function createWindow(): void {
  console.log('start app...')

  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 700,
    // autoHideMenuBar: true,
    // resizable: false, //不允许缩放
    // frame: false, //无边窗口
    show: false,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false,
      nodeIntegration: true,
      contextIsolation: false
    }
  })

  mainWindow.on('ready-to-show', () => {
    mainWindow.show() //配置了show为false，当ready-to-show准备好的时候才显示窗口，防止白屏
  })

  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  // HMR for renderer base on electron-vite cli.
  // Load the remote URL for development or the local html file for production.
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
    console.log(__dirname)
  }

  ipcMain.handle('dialog:openFile', async () => {
    const { canceled, filePaths } = await dialog.showOpenDialog({})

    if (canceled) {
      console.log(canceled)
      return
    } else {
      console.log(filePaths[0])
      return filePaths[0] //返回文件名给渲染进程
    }
  })

  // 读取文件内容
  ipcMain.handle('readFile', async (_, sendData: string) => {
    let path = ''
    if (sendData == '') {
      path = join(__dirname, '/index.js')
    } else {
      path = sendData
    }
    console.log(path)
    fs.readFile(path, 'utf8', (err, data) => {
      if (err) {
        console.error(err)
        return
      }
      mainWindow.webContents.send('fileValue', data)
    })
  })

  ipcMain.on('set-title', async () => {
    const { canceled, filePaths } = await dialog.showOpenDialog({})

    if (canceled) {
      console.log(canceled)
      return
    } else {
      console.log(filePaths[0])
      return filePaths[0] //返回文件名给渲染进程
    }
  })
  ipcMain.on('closeHandle', (event, value) => {
    const flag = mainWindow.isMinimized()
    if (!!flag) mainWindow.minimize()
  })

  ipcMain.handle('window:hide', (event, value) => {
    // const webContents = event.sender
    // console.log(webContents);
    const flag = mainWindow.isMinimized()
    console.log(flag)

    if (!flag) mainWindow.minimize()
  })

  ipcMain.handle('window:change', () => {
    const flag = mainWindow.isMaximized()
    console.log(flag)

    if (!flag) {
      mainWindow.maximize()
    } else {
      mainWindow.restore()
    }
  })

  ipcMain.handle('window:close', () => {
    mainWindow.close()
  })

  ipcMain.on('makeMenu', (e) => {
    // 自定义菜单
    const template: Object[] = [
      {
        label: '文件',
        submenu: [
          {
            label: '打开文件',
            click: async () => {
              const path: any = await dialog.showOpenDialogSync({})
              if (!path) {
                dialog.showMessageBoxSync({
                  type: 'warning',
                  title: '取消',
                  message: '你已取消'
                })
              } else {
                dialog.showMessageBoxSync({
                  type: 'info',
                  title: '成功',
                  message: `${path}`
                })
              }
            }
          },
          { type: 'separator' },
          { label: '打开文件夹' },
          { type: 'separator' },
          { label: '保存文件' }
        ]
      },
      {
        label: '类型',
        submenu: [
          { label: '选项1', type: 'checkbox' },
          { label: '选项2', type: 'checkbox' },
          { label: '选项3', type: 'checkbox' },
          { type: 'separator' },
          { label: 'item1', type: 'radio' },
          { label: 'item2', type: 'radio' }
        ]
      }
    ]

    //利用上述的模板然后生成一个菜单项
    const menu = Menu.buildFromTemplate(template)

    //将上述的自定义菜单添加到应用里
    Menu.setApplicationMenu(menu)
    // const win = e.sender
    // menu.popup({ window: BrowserWindow.fromWebContents(win) })
    e.returnValue = 'asdasd'
  })

  // 在自定义菜单上面添加一项
  ipcMain.on('makeMenuItem1', (e, val) => {
    console.log(val)

    const menuNow = Menu.getApplicationMenu()
    const newMent = new MenuItem({
      label: val,
      type: 'normal'
    })
    console.log(newMent)

    // let menu = new Menu()
    menuNow?.append(newMent)
    Menu.setApplicationMenu(menuNow)
  })

  // 右键呼出菜单
  ipcMain.handle('showRightMenu', (e) => {
    return new Promise((res, rej) => {
      const temp: Object[] = [
        { id: 1, label: '保存', role: 'normal' },
        {
          id: 2,
          label: 'webContents对象',
          role: 'normal',
          click: (e) => {
            // const webContents = mainWindow.webContents
            console.log('---------------------')
            console.log(webContents.getAllWebContents())
            console.log(mainWindow.webContents.getZoomLevel())
            console.log('---------------------')
          }
        },
        {
          id: 3,
          label: '打开控制台',
          role: 'normal',
          click: () => {
            // 切换控制台
            BrowserWindow.fromWebContents(e.sender)?.webContents.toggleDevTools()
            // 打开控制台
            // BrowserWindow.fromWebContents(e.sender)?.webContents.openDevTools()
          }
        },
        {
          id: 4,
          label: '查看所有窗口',
          role: 'normal',
          click: () => {
            const wins = BrowserWindow.getAllWindows()
            console.log('---------------')
            console.log(wins)
            console.log('---------------')

            mainWindow.webContents.send('getWinMsg', wins.length)
          }
        },
        {
          id: 5,
          label: '创建文件cc.txt并写入',
          role: 'normal',
          click: () => {
            const path: string = join(__dirname, '/index.js')
            const desktopPath = join(os.homedir(), 'Desktop/cc.txt')
            console.log(desktopPath)
            /**
             *  第二个参数flags：
             *  r:以读取模式打开文件，如果文件不存在则发生异常
             *  r+：以读写模式打开文件，如果文件不存在则发生异常
             *  rs+：以同步读写模式打开文件，命令操作系统绕过本地文件系统缓存
             */
            fs.open(desktopPath, 'a+', (err, fd) => {
              // 打开文件夹 创建缓冲区放置数据
              let readBuf = Buffer.alloc(1024), //读取多少字节
                bufOffset = 0,
                readbufLength = readBuf.length,
                filePosition = 50 //提供缓冲区的第50个字节开始

              // 读取文件
              // fs.read(
              //   fd,
              //   readBuf,
              //   bufOffset,
              //   readbufLength,
              //   filePosition,
              //   (err, readBytes, buffer) => {
              //     console.log('------------------------------')
              //     console.log('err:', err)
              //     console.log('readBytes:', readBytes) //读取缓冲区的字节数
              //     console.log('buffer:', buffer) //读取缓冲区的内容
              //     console.log('--------------------------------')
              //   }
              // )
              fs.read(fd, (err, readBytes, buffer) => {
                console.log('------------------------------')
                console.log('err:', err)
                console.log('readBytes:', readBytes) //读取缓冲区的字节数
                console.log('buffer:', buffer) //读取缓冲区的内容
                console.log('--------------------------------')
              })

              // 写入文件
              let writeBuf_Write = Buffer.from('我是要写入的内容；'),
                bufPosition_Write = 0, //待写入数据在缓冲区的起始位置
                writbufLength_Write = writeBuf_Write.length, //待写入数据的长度
                filePosition_Write = null //从文件中的什么位置开始写入数据

              // fs.write(
              //   fd,
              //   writeBuf_Write,
              //   bufPosition_Write,
              //   writbufLength_Write,
              //   filePosition_Write,
              //   (err, bytesWritten, buffer) => {
              //     console.log(err)
              //     console.log(bytesWritten)
              //     console.log(buffer.toString())
              //   }
              // )
              fs.write(fd, writeBuf_Write, (err, bytesWritten, buffer) => {
                console.log(err)
                console.log(bytesWritten)
                console.log(buffer.toString())
              })

              // 关闭文件
              fs.close(fd, () => {
                console.log('操作完毕，关闭文件')
              })
            })
          }
        }
      ]
      const menuR = Menu.buildFromTemplate(temp)
      menuR.popup({ window: mainWindow })
      res('打开控制台，这里是使用invoke和handle来通信的，使用handle的时候里面的函数需要时promise函数，这样在渲染进程中可以获得返回值')
    })
  })

  // 创建一个子窗口
  ipcMain.on('open-child-window', (ev) => {
    const childWindow = new BrowserWindow({
      width: 400,
      height: 300,
      parent: mainWindow,
      // frame: false, //无边窗口
      autoHideMenuBar: true,
      modal: true,
      webPreferences: {
        nodeIntegration: true,
        contextIsolation: true
      }
    })

    childWindow.loadFile(join(__dirname, '../renderer/child.html'))
    console.log(__dirname)

    childWindow.on('closed', () => {
      console.log('child window closed')
    })
  })
}

// set-title通道
const handleSetTitle = (event, title) => {
  console.log(title)
  if (title) {
    app.quit()
  }
  const webContents = event.sender
  const win = BrowserWindow.fromWebContents(webContents)
  win?.setTitle(title)
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  // Set app user model id for windows
  electronApp.setAppUserModelId('com.electron')

  // Default open or close DevTools by F12 in development
  // and ignore CommandOrControl + R in production.
  // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
  app.on('browser-window-created', (_, window) => {
    optimizer.watchWindowShortcuts(window)
  })

  // // 监听键盘事件，当用户esc退出的时候关闭app
  // const ret = globalShortcut.register('esc', () => {
  //   console.log('put on esc')
  //   app.quit()
  // })
  // if (!ret) console.warn('esc fail')

  createWindow()

  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

// In this file you can include the rest of your app"s specific main process
// code. You can also put them in separate files and require them here.

// app.on('will-quit', () => {
//   globalShortcut.unregisterAll() //注销所有快捷键
// })
